#pragma once
#include "Server.h"
#include <iostream>
#include <string>

using namespace std;

Server::Server(void)
{
	clientCount = 0;

    if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
    {
        cerr<<"Socket Initialization: Error with WSAStartup\n";
        system("pause");
        WSACleanup();
        exit(10);
    }
	std::cout << "Socket WSAStartup Initialized" << endl;

    //Create a socket
    mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if ( mySocket == INVALID_SOCKET )
    {
        cerr<<"Socket Initialization: Error creating socket"<<endl;
        system("pause");
        WSACleanup();
        exit(11);
    }

	std::cout << "Socket Created" << endl;

    myBackup = mySocket;
}


Server::~Server(void)
{
	WSACleanup();
}

void Server::sendUserList() {
	string a = getUserList();
	cout << "Sending user list" << endl;
	SendToAll((char*)a.c_str());
}

string Server::getUserList() {
	string message = "U:";
	for(int i=0;i<clientCount;i++) {
		//message.append(clientList[i]->getName());
		message.append(clientList2.get(i)->getName());
		message.append(",");
	}
	return message;
}

void Server::start(int port) {
	std::cout << "Start Hosting" << std::endl;
    //BINDING
	std::cout << "Binding started" << std::endl;
    myAddress.sin_family = AF_INET;
    myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" );
    myAddress.sin_port = htons( port );
    
    //cout<<"BIND TO PORT "<<port<<endl;

    if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR )
    {
        cerr<<"ServerSocket: Failed to connect\n";
        system("pause");
        WSACleanup();
        exit(14);
    }
	std::cout << "Socket bound on port: " << port << endl;
	//START LISTENING FOR CONNECTIONS
    Listen();
}

void Server::SendToAll(char text[]){
	cout << text << endl;
	for(int i=0; i<clientCount;i++) {
		//clientList[i]->SendData(text);
		clientList2.get(i) -> SendData(text);
	}
}

void Server::disonnectClient(int scp) {
	ServerClient* sc = (ServerClient*)scp;
	string message = "[";
	message.append(sc->getName());
	message.append("] disconnected");
	SendToAll((char*)message.c_str());
	cout << "Client poiter disconnected: " << sc << endl;
	
	clientList2.remove(sc);
	clientCount--;
	sendUserList();

	/*for(int i=0; i<clientCount; i++) {
		if(clientList[i] == sc) {
			for(int j=i;j<clientCount-1;j++) {
				clientList[j] = clientList[j+1];
			}
			clientCount--;
			sendUserList();
			break;
		}
	}*/
	sc->~ServerClient();
}

//PRIVATE METHODS

void Server::Listen() {
	while(true) {
		cout << endl;
		cout << "LISTEN FOR CLIENT" << endl;
    
		if ( listen ( mySocket, 1 ) == SOCKET_ERROR )
		{
			cerr<<"ServerSocket: Error listening on socket\n";
			system("pause");
			WSACleanup();
			exit(15);
		}
    
		//cout<<"ACCEPT CONNECTION..."<<endl;
		
		acceptSocket = accept( myBackup, NULL, NULL );
		
		while ( acceptSocket == SOCKET_ERROR )
		{
			acceptSocket = accept( myBackup, NULL, NULL );
		}

		SOCKET* tempSocket = new SOCKET(acceptSocket);
		//Recive Name
		char buffer[256];
		int i = recv( (*tempSocket), buffer, 256, 0 );
		buffer[i] = '\0';
		string name(buffer);

		//Add Client to List
		string message ="[SERVER] Welcome ";
		message.append(name);
		send(acceptSocket,message.c_str(),message.length(),0);

		string cmessage = "[";
		cmessage.append(name);
		cmessage.append("] connected");
		SendToAll((char*)cmessage.c_str());
		std::cout << "Client [" << name << "] connected" << std::endl;
		std::cout << "Client [" << name << "] recived socket pointer: " << tempSocket << std::endl;
		cout << endl;

		ServerClient* sc = new ServerClient;
		(*sc).setName(name);
		(*sc).setSocket((*tempSocket));
		(*sc).setCallback(this);
		clientList2.add(sc);
		//clientList[clientCount] = sc;
		clientCount++;
		(*sc).run();
		Server::sendUserList();
	}
}